# -*- coding: utf-8 -*-
import sys
import ui_tcpserver
from PyQt5.QtCore import pyqtSignal,QDataStream,QTime,QByteArray,QIODevice,QFile
from PyQt5.QtWidgets import QWidget,QApplication,QMessageBox,QFileDialog
from PyQt5.QtNetwork import QHostAddress,QTcpServer

class TcpServer(ui_tcpserver.Ui_Form,QWidget):
    sendFileName = pyqtSignal(str)
    def __init__(self):
        super(TcpServer,self).__init__()
        self.ui = ui_tcpserver.Ui_Form()
        self.ui.setupUi(self)

        self.tcpport = 6666
        self.tcpServer = QTcpServer(self)

        self.tcpServer.newConnection.connect(self.sendMessage)
        self.ui.serverOpenBtn.clicked.connect(self.serverOpenBtn)
        self.ui.serverSendBtn.clicked.connect(self.serverSendBtn)
        self.ui.serverCloseBtn.clicked.connect(self.serverCloseBtn)

        self.initServer()

    #初始化
    def initServer(self):
        self.payloadSize = 64*1024
        self.TotalBytes = 0
        self.bytesWritten = 0;
        self.bytesToWrite = 0;
        self.fileName = ""
        self.theFileName = ""

        self.clientConnection = QTcpServer()
        self.time = QTime()
        self.outBlock = QByteArray()
        self.localFile = QFile()

        self.ui.serverStatusLabel.setText("请选择要传送的文件")
        self.ui.progressBar.reset()
        self.ui.serverOpenBtn.setEnabled(True)
        self.ui.serverSendBtn.setEnabled(False)

        self.tcpServer.close()

    #开始发送数据
    def sendMessage(self):
        self.ui.serverSendBtn.setEnabled(False)
        self.clientConnection = self.tcpServer.nextPendingConnection()
        self.clientConnection.bytesWritten.connect(self.updateClientProgress)
        self.ui.serverStatusLabel.setText("开始传送文件{}！".format(self.theFileName))

        self.localFile = QFile(self.fileName)

        if not self.localFile.open(QIODevice.ReadOnly):
            QMessageBox.warning(self,"应用程序","无法读取文件{}:\n{}".format(self.fileName,self.localFile.errorString()))
            return

        self.TotalBytes = self.localFile.size()
        sendOut = QDataStream(self.outBlock,QIODevice.WriteOnly)
        sendOut.setVersion(QDataStream.Qt_4_7)#不确定版本
        self.time.start()

        fileNameList = self.fileName.split('/')
        currentFile = fileNameList[-1].split("'")[0]
        sendOut.writeInt64(0)
        sendOut.writeInt64(0)
        sendOut.writeQString(currentFile)

        self.TotalBytes += len(self.outBlock)
        sendOut.device().seek(0)
        sendOut.writeInt64(self.TotalBytes)
        sendOut.writeInt64(len(self.outBlock)-16)
        self.bytesToWrite = self.TotalBytes - self.clientConnection.write(self.outBlock)
        self.outBlock.resize(0)

    #更新进度条
    def updateClientProgress(self,numBytes):
        QApplication.processEvents()
        self.bytesWritten += int(numBytes)
        if self.bytesToWrite>0:
            self.outBlock = self.localFile.read(min(self.bytesToWrite,self.payloadSize))
            self.outBlock = QByteArray(self.outBlock)
            self.bytesToWrite -= int(self.clientConnection.write(self.outBlock))
            self.outBlock.resize(0)
        else:
            self.localFile.close()

        self.ui.progressBar.setMaximum(self.TotalBytes)
        self.ui.progressBar.setValue(self.bytesWritten)

        useTime = self.time.elapsed()
        speed = self.bytesWritten/useTime
        format1 = self.bytesWritten/(1024*1024)
        format2 = speed*1000/(1024*1024)
        format3 = self.TotalBytes/(1024*1024)
        format4 = useTime/1000
        format5 = self.TotalBytes/speed/1000 - useTime/1000
        self.ui.serverStatusLabel.setText("已发送 {:.0f}MB ({:.2f}MB/s) \n共{:.0f}MB "
                                          "已用时：{:.0f}秒\n估计剩余时间：{:.0f}秒".format(format1
                                                            ,format2,format3,format4,format5))

        if self.bytesWritten == self.TotalBytes:
            self.localFile.close()
            self.tcpServer.close()
            self.ui.serverStatusLabel.setText("传送文件 {} 成功".format(self.theFileName))

    #打开按钮
    def serverOpenBtn(self):
        fileNameTuple = QFileDialog.getOpenFileName(self)
        self.fileName = str(fileNameTuple).split(',')[0].lstrip('(').strip("'")

        if len(self.fileName):
            fileNameList = self.fileName.split('/')
            self.theFileName = fileNameList[-1].split("'")[0]

            self.ui.serverStatusLabel.setText("要传送的文件为：{}".format(self.theFileName))
            self.ui.serverSendBtn.setEnabled(True)
            self.ui.serverOpenBtn.setEnabled(False)

    #发送按钮
    def serverSendBtn(self):
        if not self.tcpServer.listen(QHostAddress.Any,self.tcpport):
            print(self.tcpServer.errorString())
            self.close()
            return

        self.ui.serverStatusLabel.setText("等待对方接收......")
        self.sendFileName.emit(self.theFileName)


    #关闭按钮
    def serverCloseBtn(self):
        if self.tcpServer.isListening():
            self.tcpServer.close()
            if self.localFile.isOpen():
                self.localFile.close()
            self.clientConnection.abort()

        self.close()


    #被对方拒绝
    def refused(self):
        self.tcpServer.close()
        self.ui.serverStatusLabel.setText("对方拒绝接收！")


    #关闭事件
    def closeEvent(self, QCloseEvent):
        self.serverCloseBtn()




if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = TcpServer()
    win.show()
    sys.exit(app.exec_())



